#include <iostream>
#include <vector>
#include <time.h>
#include "FixedLengthpool.h"
#include "ConcurrentAlloc.h"

using std::cout;
using std::endl;


void TestblockectPool()
{
	kele::blockectPool<int> pool;
	int* ptr = pool.New();
	pool.Delete(ptr);
}

void TestblockectPool1()
{
	int size = 100000;
	int Polling = 5;
	std::vector<int*> vp;
	kele::blockectPool<int> pool;
	size_t begin = clock();
	for (int r = 0; r < Polling; ++r)
	{
		for (int i = 0; i < size; ++i)
		{
			vp.push_back(pool.New());
		}
		for (auto& ptr : vp)
		{
			pool.Delete(ptr);
		}
	}
	size_t end = clock();
	cout << end - begin << endl;
}

struct TreeNode
{
	int _val;
	TreeNode* _left;
	TreeNode* _right;
	TreeNode()
		:_val(0)
		, _left(nullptr)
		, _right(nullptr)
	{}
};

void TestblockectPool2()
{
	// 申请释放的轮次
	const size_t Rounds = 3;
	// 每轮申请释放多少次
	const size_t N = 1000000;
	size_t begin1 = clock();
	std::vector<TreeNode*> v1;
	v1.reserve(N);
	for (size_t j = 0; j < Rounds; ++j)
	{
		for (int i = 0; i < N; ++i)
		{
			v1.push_back(new TreeNode);
		}
		for (int i = 0; i < N; ++i)
		{
			delete v1[i];
		}
		v1.clear();
	}
	size_t end1 = clock();
	kele::blockectPool<TreeNode> TNPool;
	size_t begin2 = clock();
	std::vector<TreeNode*> v2;
	v2.reserve(N);
	for (size_t j = 0; j < Rounds; ++j)
	{
		for (int i = 0; i < N; ++i)
		{
			v2.push_back(TNPool.New());
		}
		for (int i = 0; i < 100000; ++i)
		{
			TNPool.Delete(v2[i]);
		}
		v2.clear();
	}
	size_t end2 = clock();
	cout << "new cost time:" << end1 - begin1 << endl;
	cout << "blockect pool cost time:" << end2 - begin2 << endl;
}

void cache()
{
	int n = 5;
	std::vector<int*> vp;
	for (int i = 0; i < 1025; ++i)
	{
		cout << i << endl;
		if(i == 208)
			int i = 0;
		vp.push_back((int*)ConcurrentAlloc(i + 1));
	}
	for (auto& ptr : vp)
	{
		ConcurrentFree(ptr);
	}
}

void TestThreadCache()
{
	std::thread thd1(cache);
	std::thread thd2(cache);
	std::thread thd3(cache);
	thd1.join();
	thd2.join();
	thd3.join();

}

void Testnpagenum()
{
	for (size_t i = 1; i <= MAX_BYTES; i += 10)
	{
		cout << i << ":" << ClassSize::Nummovepage(i) << endl;
	}
}

void Testnblocknum()
{
	for (size_t i = 1; i <= MAX_BYTES; i *= 10)
	{
		cout << i << ":" << ClassSize::Nummovesize(i) << endl;
	}
}

void TestThreadCache2()
{
	int n = 7;
	std::vector<void*> vp;
	for (int i = 0; i < n; ++i)
	{
		cout << i << endl;
		vp.push_back(ConcurrentAlloc(i + 1));
	}
	int i = 1;
	for (auto& ptr : vp)
	{
		cout << i++ << endl;
		ConcurrentFree(ptr);
	}
}

void TestBigBlock()
{
	void* ptr1 = ConcurrentAlloc(MAX_BYTES + 1); // 256 kB + 1
	ConcurrentFree(ptr1);

	void* ptr2 = ConcurrentAlloc(NPAGES << PAGE_SHIFT); // 129 * 8 kB
	ConcurrentFree(ptr2);

	cout << "success" << endl;
}


void testsize()
{
	cout << sizeof(std::mutex) << endl;
	cout << sizeof(std::unique_lock<std::mutex>) << endl;
	cout << sizeof(ThreadCache) << endl;
}

void test_linux_sysalloc()
{
	char* ptr = (char*)SystemAlloc(1); // 8KB
	for(size_t i = 0; i < 1 << PAGE_SHIFT; ++i)
	{
		cout << i << endl;
		*(ptr + i) = '0';
	}
	cout << "success" << endl;
}


// int main()
// {
// 	// TestThreadCache2();
// 	TestThreadCache();
// 	// Testnpagenum();
// 	// Testnblocknum();
// 	// TestBigBlock();
// 	// testsize();
// 	// test_linux_sysalloc();
// 	return 0;
// }